package eu.ahsx.limboa.media
{
	import eu.ahsx.limboa.utils.Params;
	import eu.ahsx.limboa.utils.Token;
	
	/**
	 * 	Representation of a file.
	 * 	This class is the entry point for starting working with assets file. 
	 * 	It provide convenient way to load, store, retrieve file throughout the application. 
	 * 
	 * 	@author Masy Alexandre
	 * 
	 * 	@example The following example load an Image. When the image is loaded, the callback function is fired and the content is retrieved
	 * 	<listing>
	 * 	AssetsFile.load("image.jpg", AssetsFileType.IMAGE, {onComplete:imageLoaded});
	 * 	function imageLoaded(file:AssetsFile):void
	 * 	{
	 * 		var bmp:Bitmap = file.getContent();
	 * 	}
	 * </listing>
	 * */
	public class MediaFile
	{
		/**
		 * 	Debug mode ?
		 * */
		public static var debug:Boolean = false;
		
		/**
		 *	file id. Used to recover the file. 
		 * */
		public var id:String;
		
		/**
		 * 	File url
		 * */
		public var url:String
		
		/**
		 * 	Type
		 * */
		public var type:String
		
		/**
		 * 	Name of the file
		 * */
		public var name:String;
		
		/**
		 * 	Info
		 * 	@see com.globulebleu.assets.AssetsFileInfo
		 * */
		public var info:MediaFileInfo;
		
		/**
		 * 	Priority
		 * 	@see com.globulebleu.assets.AssetsPriority
		 * */
		public var priority:int;
		
		/**
		 * 	Forced the core to download the file
		 * */
		public var forced:Boolean = false;
		
		/**
		 * 	Time to keep the file in seconds.
		 * 	If the value is -1, then the file will be kept indefinitely
		 * */
		public var maxtime:int = -1;
		
		/**
		 * 	Time the file have been kept.
		 * */
		internal var time:int = -1;
		
		/**
		 * 	Start function
		 * 	@private
		 * */
		internal var start:Array;
		
		/**
		 * 	Init function
		 * 	@private
		 * */
		internal var init:Array;
		
		/**
		 * 	Progress function
		 * 	@private
		 * */
		internal var progress:Array;
		
		/**
		 * 	Complete function
		 * 	@private
		 * */
		internal var complete:Array;
		
		/**
		 * 	Done function
		 * 	@private
		 * */
		internal var done:Array;
		 
		/**
		 * 	Error function
		 * 	@private 
		 * */
		internal var error:Array;
	
		/**
		 * 	Loader
		 *  @private
		 * */	
		internal var loader:IAssetsLoader;
		
		/**
		 * 	Params
		 * */
		public var params:Object;
		
		/**
		 * 	Create an AssetsFile and add it to the loading list
		 * 
		 * 	@param	file String	url 
		 * 	@param	type	String	type of file to load
		 * 	@param	params Object parameter the loading.
		 * 						<ul>
		 * 						<li><b>onInit</b>:Function called when the loading initialised</li>
		 * 						<li><b>onStart</b>:Function called when the loading start</li>
		 * 						<li><b>onProgress</b>:Function called when the loading progress</li>
		 * 						<li><b>onComplete</b>:Function called when the loading is completed</li>
		 * 						<li><b>onDone</b>:Function called when the loading is done</li>
		 * 						<li><b>forced</b>:Boolean indicate if the loading have to be forced or not. If true, the file will be loaded even if it has already been loaded before. If false, the file will not be loaded twice. Default, false.</li>
		 * 						<li><b>priority</b>:String indicated the loading priority of the file. See AssetsPriority</li>
		 * 						<li><b>maxtime</b>:Int indicated how many times in second to keep the file, when the loading is completed. If the value equals to -1, the file will be kept forever. Default value : 5 seconds.</li>
		 * 						<li><b>fontname</b>:The name of the font to embed. Required if loading a font file</li>
		 * 						</ul>
		 * 						
		 * 	@param	seq	String	sequence id
		 * 	@return Boolean Return true if the file is added to the queue, false if not
		 *  @throws com.globulebleu.assets.WRONG_URL	Your AssetsFile does not define a valid url
		 *  @throws com.globulebleu.assets.WRONG_TYPE	Your AssetsFile does not define this filetype
		 * 	@langversion ActionScript 3.0
		 * 	@playerversion Flash 9
		 * */
		public static function load(url:String, type:String, params:Object):Boolean
		{
			var f:MediaFile = create(url, type, params); 
			return MediaCore.load(f);
		}
		
		/**
		 * 	Retrieve a file by its url
		 * 	
		 * 	@param	url String
		 * 	@return AssetsFile
		 * 	@langversion ActionScript 3.0
		 * 	@playerversion Flash 9
		 * */
		public static function getByURL(url:String):MediaFile
		{
			return MediaCore.getByURL(url);
		}
		
		/**
		 * 	Retrieve the content of a file
		 * 
		 * 	@return the content. The type depends on the filetype of the file
		 * 	@langversion ActionScript 3.0
		 * 	@playerversion Flash 9
		 * */
		public function getContent(core:MediaCore = null):*
		{
			return MediaCore.getContent(this);
		}
		
		/**
		 * 	Remove any references to the file in the library
		 * 
		 * 	@langversion ActionScript 3.0
		 * 	@playerversion Flash 9
		 * */
		public function remove():void
		{
			MediaCore.remove(this);
		}
		
		/**
		 * 	Add an Init callback
		 * 	
		 * 	@param callback Function
		 * 	@langversion ActionScript 3.0
		 * 	@playerversion Flash 9
		 * */
		public function addInit(callback:Function):void
		{
			if (this.init.indexOf(callback)==-1)
				this.init.push( callback );
		}
		
		/**
		 * 	Remove an init callback
		 * 
		 * 	@param callback Function
		 * 	@langversion ActionScript 3.0
		 * 	@playerversion Flash 9
		 * */
		public function removeInit(callback:Function):void
		{
			var index:int = this.init.indexOf(callback);
			if (index > -1)
				this.init = this.init.slice(index, 1);
		}
		
		/**
		 * 	Add an Start callback
		 * 	
		 * 	@param callback Function
		 * 	@langversion ActionScript 3.0
		 * 	@playerversion Flash 9
		 * */
		public function addStart(callback:Function):void
		{
			if (this.start.indexOf(callback)==-1)
				this.start.push( callback );
		}
		
		/**
		 * 	Remove an start callback
		 * 
		 * 	@param callback Function
		 * 	@langversion ActionScript 3.0
		 * 	@playerversion Flash 9
		 * */
		public function removeStart(callback:Function):void
		{
			var index:int = this.start.indexOf(callback);
			if (index > -1)
				this.start = this.start.slice(index, 1);
		}
		
		/**
		 * 	Add an Progress callback
		 * 	
		 * 	@param callback Function
		 * 	@langversion ActionScript 3.0
		 * 	@playerversion Flash 9
		 * */
		public function addProgress(callback:Function):void
		{
			if (this.progress.indexOf(callback)==-1)
				this.progress.push( callback );
		}
		
		/**
		 * 	Remove an progress callback
		 * 
		 * 	@param callback Function
		 * 	@langversion ActionScript 3.0
		 * 	@playerversion Flash 9
		 * */
		public function removeProgress(callback:Function):void
		{
			var index:int = this.progress.indexOf(callback);
			if (index > -1)
				this.progress = this.progress.slice(index, 1);
		}
		
		/**
		 * 	Add an Complete callback
		 * 	
		 * 	@param callback Function
		 * 	@langversion ActionScript 3.0
		 * 	@playerversion Flash 9
		 * */
		public function addComplete(callback:Function):void
		{
			if (this.complete.indexOf(callback)==-1)
				this.complete.push( callback );
		}
		
		/**
		 * 	Remove an complete callback
		 * 
		 * 	@param callback Function
		 * 	@langversion ActionScript 3.0
		 * 	@playerversion Flash 9
		 * */
		public function removeComplete(callback:Function):void
		{
			var index:int = this.complete.indexOf(callback);
			if (index > -1)
				this.complete = this.complete.slice(index, 1);
		}
		
		/**
		 * 	Add an Done callback
		 * 	
		 * 	@param callback Function
		 * 	@langversion ActionScript 3.0
		 * 	@playerversion Flash 9
		 * */
		public function addDone(callback:Function):void
		{
			if (this.done.indexOf(callback)==-1)
				this.done.push( callback );
		}
		
		/**
		 * 	Remove an done callback
		 * 
		 * 	@param callback Function
		 * 	@langversion ActionScript 3.0
		 * 	@playerversion Flash 9
		 * */
		public function removeDone(callback:Function):void
		{
			var index:int = this.done.indexOf(callback);
			if (index > -1)
				this.done = this.done.slice(index, 1);
		}
		
		/**
		 * 	Add an Error callback
		 * 	
		 * 	@param callback Function
		 * 	@langversion ActionScript 3.0
		 * 	@playerversion Flash 9
		 * */
		public function addError(callback:Function):void
		{
			if (this.error.indexOf(callback)==-1)
				this.error.push( callback );
		}
		
		/**
		 * 	Remove an error callback
		 * 
		 * 	@param callback Function
		 * 	@langversion ActionScript 3.0
		 * 	@playerversion Flash 9
		 * */
		public function removeError(callback:Function):void
		{
			var index:int = this.error.indexOf(callback);
			if (index > -1)
				this.error = this.error.slice(index, 1);
		}
		
		/***
		 *	Create an AssetsFile
		 * 
		 * 	@param	file String	url 
		 * 	@param	type	String	type of file to load
		 * 	@param	params Object parameter the loading.
		 * 						<ul>
		 * 						<li><b>onInit</b>:Function called when the loading initialised</li>
		 * 						<li><b>onStart</b>:Function called when the loading start</li>
		 * 						<li><b>onProgress</b>:Function called when the loading progress</li>
		 * 						<li><b>onComplete</b>:Function called when the loading is completed</li>
		 * 						<li><b>onDone</b>:Function called when the loading is done</li>
		 * 						<li><b>forced</b>:Boolean indicate if the loading have to be forced or not. If true, the file will be loaded even if it has already been loaded before. If false, the file will not be loaded twice. Default, false.</li>
		 * 						<li><b>priority</b>:String indicated the loading priority of the file. See AssetsPriority</li>
		 * 						<li><b>maxtime</b>:Int indicated how many times in second to keep the file, when the loading is completed. If the value equals to -1, the file will be kept forever. Default value : 5 seconds.</li>
		 * 						</ul>
		 * 						
		 * 	@param	seq	String	sequence id
		 * 	@return Boolean Return true if the file is added to the queue, false if not
		 *  @throws com.globulebleu.assets.WRONG_URL	Your AssetsFile does not define a valid url
		 *  @throws com.globulebleu.assets.WRONG_TYPE	Your AssetsFile does not define this filetype
		 * 	@private
		 * 	@langversion ActionScript 3.0
		 * 	@playerversion Flash 9
		 * */ 
		internal static function create(url:String, type:String, params:Object):MediaFile
		{
			var f:MediaFile = new MediaFile();
			
			f.url = url;
			if (url == "" || url == null || url.length <= 3)
				throw MediaError.WRONG_URL;
			
			f.type = type;
			if (!MediaFileType.validate(type))
				throw MediaError.WRONG_TYPE;
			
			f.priority = Params.getOrNull("priority", params);
			f.forced = Params.getBool("forced", params, false);
			f.maxtime = Params.getInt("maxtime", params, -1);
			f.name = Params.getStringOr("name", params);
			
			var c:Function;
			
			f.start = [];
			c = Params.getOrNull("onStart", params);
			if (c != null)
				f.start.push( c );
			
			f.init = [];
			c = Params.getOrNull("onInit", params);
			if (c != null)
				f.init.push( c );
			
			f.progress = [];
			c = Params.getOrNull("onProgress", params);
			if (c != null)
				f.progress.push( c );
			
			f.complete = [];
			c = Params.getOrNull("onComplete", params);
			if (c != null)
				f.complete.push( c );
			
			f.done = [];
			c = Params.getOrNull("onDone", params);
			if (c != null)
				f.done.push( c );
			
			f.error = [];
			c = Params.getOrNull("onError", params);
			if (c != null)
				f.error.push( c );
			
			f.info = new MediaFileInfo();
			f.params = params;
			
			return f;
		}
	}
}